From b5b9ba0b36710218a67b1cc283b05b2f827ac099 Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Mon, 7 Feb 2022 07:10:14 -0700 Subject: [PATCH] convert garmin gpi to Format class (#849) * convert garmin_gpi to Format class * const member funcs * flush out includes --- garmin_gpi.cc | 336 ++++++++------------------------- garmin_gpi.h | 501 +++++++++++++++++++++++++++++++++++++++----------- vecs.h | 4 +- 3 files changed, 466 insertions(+), 375 deletions(-) diff --git a/garmin_gpi.cc b/garmin_gpi.cc index 74fc07b33..36d1aca91 100644 --- a/garmin_gpi.cc +++ b/garmin_gpi.cc @@ -44,28 +44,29 @@ * support category from GMSD "Garmin Special Data" */ -#include // for stable_sort -#include // for tolower -#include // for int32_t, int16_t, uint16_t -#include // for SEEK_CUR, SEEK_SET -#include // for atoi -#include // for strlen, strncmp -#include // for time, time_t, gmtime +#include "garmin_gpi.h" #include // for QByteArray, operator== -#include // for QList<>::iterator, QList +#include // for QList #include // for QString, operator+, operator< #include // for QThread -#include // for QVector #include // for CaseInsensitive #include // for foreach, Q_UNUSED -#include "defs.h" -#include "garmin_gpi.h" +#include // for stable_sort +#include // for tolower +#include // for uint32_t, int32_t +#include // for SEEK_CUR, SEEK_SET +#include // for atoi +#include // for strlen, strncmp +#include // for time, gmtime, time_t, tm +#include // for unique_ptr + +#include "defs.h" // for Waypoint, fatal, STRFROMUNICODE, le_write32, le_write16, wp_flags, warning, bounds, KPH_TO_MPS, MPH_TO_MPS, WAYPT_HAS, gpsbabel_testmode, parse_speed, WAYPT_SET, MILES_TO_METERS, MPS_TO_KPH, MPS_TO_MPH, mkgmtime, mkshort, mkshort_del_handle, mkshort_new_... #include "cet_util.h" // for cet_convert_init #include "formspec.h" // for FormatSpecificDataList #include "garmin_fs.h" // for garmin_fs_t, garmin_fs_alloc -#include "gbfile.h" // for gbfputint32, gbfgetint32, gbfgetint16, gbfputint16, gbfgetc, gbfputc, gbfread, gbftell, gbfwrite, gbfseek, gbfclose, gbfopen_le, gbfgetuint16, gbfile, gbsize_t +#include "gbfile.h" // for gbfputint32, gbfgetint32, gbfgetint16, gbfputint16, gbfgetc, gbfputc, gbfread, gbftell, gbfwrite, gbfseek, gbfclose, gbfopen_le, gbfgetuint16, gbsize_t, gbfile #include "jeeps/gpsmath.h" // for GPS_Math_Deg_To_Semi, GPS_Math_Semi_To_Deg @@ -84,152 +85,7 @@ #define GPI_ADDR_POSTAL_CODE 8 #define GPI_ADDR_ADDR 16 -static char* opt_cat, *opt_pos, *opt_notes, *opt_hide_bitmap, *opt_descr, *opt_bitmap; -static char* opt_unique, *opt_alerts, *opt_units, *opt_speed, *opt_proximity, *opt_sleep; -static char* opt_lang; -static char* opt_writecodec; -static double defspeed, defproximity; -static int alerts; - -static QVector garmin_gpi_args = { - { - "alerts", &opt_alerts, "Enable alerts on speed or proximity distance", - nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr - }, - { - "bitmap", &opt_bitmap, "Use specified bitmap on output", - nullptr, ARGTYPE_FILE, ARG_NOMINMAX, nullptr - }, - { - "category", &opt_cat, "Default category on output", - "My points", ARGTYPE_STRING, ARG_NOMINMAX, nullptr - }, - { - "hide", &opt_hide_bitmap, "Don't show gpi bitmap on device", - nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr - }, - { - "descr", &opt_descr, "Write description to address field", - nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr - }, - { - "notes", &opt_notes, "Write notes to address field", - nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr - }, - { - "position", &opt_pos, "Write position to address field", - nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr - }, - { - "proximity", &opt_proximity, "Default proximity", - nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr - }, - { - "sleep", &opt_sleep, "After output job done sleep n second(s)", - nullptr, ARGTYPE_INT, "1", nullptr, nullptr - }, - { - "speed", &opt_speed, "Default speed", - nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr - }, - { - "unique", &opt_unique, "Create unique waypoint names (default = yes)", - "Y", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr - }, - { - "units", &opt_units, "Units used for names with @speed ('s'tatute or 'm'etric)", - "m", ARGTYPE_STRING, ARG_NOMINMAX, nullptr - }, - { - "writecodec", &opt_writecodec, "codec to use for writing strings", - "windows-1252", ARGTYPE_STRING, ARG_NOMINMAX, nullptr - }, - { - "languagecode", &opt_lang, "language code to use for reading dual language files", - nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr - }, -}; - -struct reader_data_t { -public: - int D2; - char S3[9]; /* "GRMRECnn" */ - time_t crdate; /* creation date and time */ - char POI[4]; /* "POI" */ - char S8[3]; - QString group; - QString category; -}; - -struct writer_data_t { - QList waypt_list; - int sz{0}; - int alert{0}; - bounds bds; - writer_data_t* top_left{nullptr}; - writer_data_t* top_right{nullptr}; - writer_data_t* bottom_left{nullptr}; - writer_data_t* bottom_right{nullptr}; -}; - -struct gpi_waypt_data_t { - int sz; - char* addr; - char* postal_code; -}; - -struct bmp_header_t { - int32_t size; - int16_t res1; - int16_t res2; - int32_t image_offset; - int32_t header_size; - int32_t width; - int32_t height; - int16_t planes; - int16_t bpp; - int32_t compression_type; - int32_t image_data_size; - int32_t resolution_h; - int32_t resolution_v; - int32_t used_colors; - int32_t important_colors; -}; - -struct gpi_bitmap_header_t { - int16_t index; - int16_t height; - int16_t width; - int16_t line_sz; - int16_t bpp; - int16_t fixed_0; - int32_t image_size; - int32_t fixed_2c; - int32_t palette_size; - int32_t tr_color; - int32_t flag2; - int32_t size_2c; -}; - -struct gpi_waypt_t { - int sz{0}; - int alerts{0}; - short mask{0}; - QString addr; - QString city; - QString country; - QString phone_nr; - QString postal_code; - QString state; -}; - -static gbfile* fin, *fout; -static uint16_t codepage; /* code-page, e.g. 1252, 65001 */ -static reader_data_t* rdata; -static writer_data_t* wdata; -static short_handle short_h; -static char units; -static time_t gpi_timestamp = 0; +#define GPI_BITMAP_SIZE sizeof(gpi_bitmap) #ifdef GPI_DBG # define PP warning("@%1$6x (%1$8d): ", gbftell(fin)) @@ -243,8 +99,8 @@ static time_t gpi_timestamp = 0; *******************************************************************************/ /* look for or initialize GMSD */ -static garmin_fs_t* -gpi_gmsd_init(Waypoint* wpt) +garmin_fs_t* +GarminGPIFormat::gpi_gmsd_init(Waypoint* wpt) { garmin_fs_t* gmsd = garmin_fs_t::find(wpt); if (wpt == nullptr) { @@ -257,14 +113,8 @@ gpi_gmsd_init(Waypoint* wpt) return gmsd; } -struct lc_string { - QByteArray lc; - QByteArray str; - int strlen{0}; -}; - -static lc_string -gpi_read_lc_string() +GarminGPIFormat::lc_string +GarminGPIFormat::gpi_read_lc_string() const { lc_string result; @@ -287,8 +137,8 @@ gpi_read_lc_string() } /* read a standard string with or without 'EN' (or whatever) header */ -static QString -gpi_read_string(const char* field) +QString +GarminGPIFormat::gpi_read_string(const char* field) const { QByteArray string; @@ -337,8 +187,8 @@ gpi_read_string(const char* field) return result; } -static void -read_header() +void +GarminGPIFormat::read_header() { int len, i; #ifdef GPI_DBG @@ -408,13 +258,9 @@ read_header() #endif } -/* gpi tag handler */ -static int read_tag(const char* caller, int tag, Waypoint* wpt); - - /* read a single poi with all options */ -static void -read_poi(const int sz, const int tag) +void +GarminGPIFormat::read_poi(const int sz, const int tag) { #ifdef GPI_DBG PP; @@ -464,8 +310,8 @@ read_poi(const int sz, const int tag) } /* read poi's following a group header */ -static void -read_poi_list(const int sz) +void +GarminGPIFormat::read_poi_list(const int sz) { int i; @@ -504,9 +350,8 @@ read_poi_list(const int sz) #endif } - -static void -read_poi_group(const int sz, const int tag) +void +GarminGPIFormat::read_poi_group(const int sz, const int tag) { int pos = gbftell(fin); #ifdef GPI_DBG @@ -544,8 +389,8 @@ read_poi_group(const int sz, const int tag) // of bytes for all record fields and all nested records, starting after the // length field) /* gpi tag handler */ -static int -read_tag(const char* caller, const int tag, Waypoint* wpt) +int +GarminGPIFormat::read_tag(const char* caller, const int tag, Waypoint* wpt) { Q_UNUSED(caller); int dist; @@ -753,8 +598,8 @@ read_tag(const char* caller, const int tag, Waypoint* wpt) * %%% gpi writer %%% * *******************************************************************************/ -static void -write_string(const char* str, const char long_format) +void +GarminGPIFormat::write_string(const char* str, const char long_format) const { int len = strlen(str); if (long_format) { @@ -765,20 +610,20 @@ write_string(const char* str, const char long_format) gbfwrite(str, 1, len, fout); } -static bool -compare_wpt_cb(const Waypoint* a, const Waypoint* b) +bool +GarminGPIFormat::compare_wpt_cb(const Waypoint* a, const Waypoint* b) { return a->shortname < b->shortname; } -static char -compare_strings(const QString& s1, const QString& s2) +char +GarminGPIFormat::compare_strings(const QString& s1, const QString& s2) { return s1.compare(s2); } -static writer_data_t* -wdata_alloc() +GarminGPIFormat::writer_data_t* +GarminGPIFormat::wdata_alloc() { auto* res = new writer_data_t; waypt_init_bounds(&res->bds); @@ -786,9 +631,8 @@ wdata_alloc() return res; } - -static void -wdata_free(writer_data_t* data) +void +GarminGPIFormat::wdata_free(writer_data_t* data) { foreach (Waypoint* wpt, data->waypt_list) { @@ -815,17 +659,15 @@ wdata_free(writer_data_t* data) delete data; } - -static void -wdata_add_wpt(writer_data_t* data, Waypoint* wpt) +void +GarminGPIFormat::wdata_add_wpt(writer_data_t* data, Waypoint* wpt) { data->waypt_list.append(wpt); waypt_add_to_bounds(&data->bds, wpt); } - -static void -wdata_check(writer_data_t* data) +void +GarminGPIFormat::wdata_check(writer_data_t* data) const { double center_lon; @@ -888,9 +730,8 @@ wdata_check(writer_data_t* data) } } - -static int -wdata_compute_size(writer_data_t* data) +int +GarminGPIFormat::wdata_compute_size(writer_data_t* data) const { int res = 0; @@ -1032,9 +873,8 @@ skip_empty_block: return res + 12; /* + 12 = caller needs info about tag header size */ } - -static void -wdata_write(const writer_data_t* data) +void +GarminGPIFormat::wdata_write(const writer_data_t* data) const { if (data->waypt_list.isEmpty()) { goto skip_empty_block; /* do not issue an empty block */ @@ -1176,9 +1016,8 @@ skip_empty_block: } } - -static void -write_category(const char*, const unsigned char* image, const int image_sz) +void +GarminGPIFormat::write_category(const char* /*unused*/, const unsigned char* image, const int image_sz) const { int sz = wdata_compute_size(wdata); sz += 8; /* string header */ @@ -1202,9 +1041,8 @@ write_category(const char*, const unsigned char* image, const int image_sz) } } - -static void -write_header() +void +GarminGPIFormat::write_header() const { time_t time = gpi_timestamp; @@ -1234,9 +1072,8 @@ write_header() gbfputint16(0, fout); } - -static void -enum_waypt_cb(const Waypoint* ref) +void +GarminGPIFormat::enum_waypt_cb(const Waypoint* ref) const { foreach (const Waypoint* cmp, wdata->waypt_list) { @@ -1259,9 +1096,8 @@ enum_waypt_cb(const Waypoint* ref) wdata_add_wpt(wdata, wpt); } - -static void -load_bitmap_from_file(const char* fname, unsigned char** data, int* data_sz) +void +GarminGPIFormat::load_bitmap_from_file(const char* fname, const unsigned char** data, int* data_sz) { int i, sz; int dest_bpp; @@ -1423,8 +1259,8 @@ load_bitmap_from_file(const char* fname, unsigned char** data, int* data_sz) * %%% global callbacks called by gpsbabel main process %%% * *******************************************************************************/ -static void -garmin_gpi_rd_init(const QString& fname) +void +GarminGPIFormat::rd_init(const QString& fname) { fin = gbfopen_le(fname, "rb", MYNAME); rdata = new reader_data_t; @@ -1446,9 +1282,8 @@ garmin_gpi_rd_init(const QString& fname) } } - -static void -garmin_gpi_wr_init(const QString& fname) +void +GarminGPIFormat::wr_init(const QString& fname) { if ((gpi_timestamp != 0) && !gpsbabel_testmode()) { /* not the first gpi output session */ time_t t = time(nullptr); @@ -1525,17 +1360,15 @@ garmin_gpi_wr_init(const QString& fname) wdata = wdata_alloc(); } - -static void -garmin_gpi_rd_deinit() +void +GarminGPIFormat::rd_deinit() { delete rdata; gbfclose(fin); } - -static void -garmin_gpi_wr_deinit() +void +GarminGPIFormat::wr_deinit() { wdata_free(wdata); mkshort_del_handle(&short_h); @@ -1553,9 +1386,8 @@ garmin_gpi_wr_deinit() } } - -static void -garmin_gpi_read() +void +GarminGPIFormat::read() { while (true) { int tag = gbfgetint32(fin); @@ -1568,11 +1400,10 @@ garmin_gpi_read() } } - -static void -garmin_gpi_write() +void +GarminGPIFormat::write() { - unsigned char* image; + const unsigned char* image; int image_sz; if (strlen(opt_cat) == 0) { @@ -1588,7 +1419,10 @@ garmin_gpi_write() image = gpi_bitmap; /* embedded GPSBabel icon in gpi format */ image_sz = GPI_BITMAP_SIZE; } - waypt_disp_all(enum_waypt_cb); + auto enum_waypt_cb_lambda = [this](const Waypoint* waypointp)->void { + enum_waypt_cb(waypointp); + }; + waypt_disp_all(enum_waypt_cb_lambda); wdata_check(wdata); write_header(); @@ -1601,27 +1435,3 @@ garmin_gpi_write() xfree(image); } } - -/**************************************************************************/ - -ff_vecs_t garmin_gpi_vecs = { - ff_type_file, - { - (ff_cap)(ff_cap_read | ff_cap_write) /* waypoints */, - ff_cap_none /* tracks */, - ff_cap_none /* routes */ - }, - garmin_gpi_rd_init, - garmin_gpi_wr_init, - garmin_gpi_rd_deinit, - garmin_gpi_wr_deinit, - garmin_gpi_read, - garmin_gpi_write, - nullptr, - &garmin_gpi_args, - CET_CHARSET_MS_ANSI, 0 /* WIN-CP1252 */ - , NULL_POS_OPS, - nullptr -}; - -/**************************************************************************/ diff --git a/garmin_gpi.h b/garmin_gpi.h index 4e2b11f0b..7457b70bd 100644 --- a/garmin_gpi.h +++ b/garmin_gpi.h @@ -1,112 +1,393 @@ -#ifndef GARMIN_GPI_H -#define GARMIN_GPI_H - -static unsigned char gpi_bitmap[] = { - 0x00,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x08,0x00,0x00,0x00,0x40,0x02,0x00,0x00, - 0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xff,0x00,0xff,0x00,0x01,0x00,0x00,0x00, - 0x6c,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x7e,0x7e,0x7e, - 0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e, - 0x7e,0x7e,0x00,0x7e,0x00,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x59,0x67,0x65,0x7f,0x7f,0x7f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x74,0x3d,0x42,0x56,0x7e,0x7e,0x7f, - 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x72,0x38,0x49,0x47,0x7e,0x7e,0x7f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7d,0x37,0x47,0x7d,0x7e,0x7e,0x7f, - 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7d,0x37,0x47,0x7d,0x7e,0x7e,0x7f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7c,0x6c,0x50,0x44,0x5e,0x4f,0x76,0x7e,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x77,0x7e,0x7f,0x7f,0x7e,0x62,0x0d,0x00,0x05, - 0x10,0x08,0x09,0x59,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x29,0x1c, - 0x4c,0x7f,0x7f,0x60,0x02,0x0c,0x2a,0x37,0x51,0x63,0x57,0x15,0x58,0x7e,0x7e,0x7f, - 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x68,0x5a,0x41,0x5f,0x5f,0x07,0x0e,0x3d,0x41,0x41, - 0x4d,0x55,0x6b,0x61,0x26,0x57,0x57,0x2b,0x2f,0x30,0x00,0x7e,0x00,0x7e,0x77,0x7d, - 0x4e,0x3d,0x3d,0x16,0x35,0x41,0x7d,0x49,0x18,0x48,0x52,0x54,0x5b,0x31,0x31,0x63, - 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x40,0x7d,0x75,0x47,0x47,0x41,0x35,0x40,0x72,0x1e, - 0x7c,0x5d,0x1d,0x20,0x49,0x3d,0x3d,0x5b,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x60,0x5c, - 0x7a,0x1a,0x1a,0x3b,0x38,0x5d,0x0e,0x59,0x7d,0x3c,0x72,0x37,0x78,0x60,0x60,0x28, - 0x4f,0x71,0x00,0x7e,0x00,0x7e,0x7e,0x43,0x33,0x69,0x69,0x17,0x22,0x7d,0x2c,0x27, - 0x2a,0x2b,0x7d,0x32,0x61,0x4f,0x4f,0x36,0x3f,0x4c,0x00,0x7e,0x00,0x7e,0x7f,0x7e, - 0x3a,0x2b,0x2b,0x45,0x1a,0x40,0x47,0x7d,0x37,0x41,0x12,0x25,0x5e,0x46,0x46,0x4d, - 0x62,0x53,0x00,0x7e,0x00,0x7e,0x7f,0x7e,0x73,0x71,0x71,0x6a,0x13,0x39,0x1b,0x45, - 0x62,0x50,0x3a,0x7e,0x7e,0x7b,0x7b,0x5c,0x5b,0x49,0x00,0x7e,0x00,0x7e,0x7f,0x7e, - 0x59,0x01,0x01,0x06,0x64,0x35,0x4e,0x3e,0x26,0x21,0x66,0x7f,0x45,0x04,0x04,0x11, - 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7e,0x59,0x01,0x01,0x06,0x64,0x35,0x4e,0x3e, - 0x26,0x21,0x66,0x7f,0x45,0x04,0x04,0x11,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7e, - 0x7c,0x0a,0x0a,0x0f,0x65,0x7d,0x74,0x71,0x7c,0x7e,0x7e,0x7e,0x58,0x03,0x03,0x2b, - 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f,0x7f,0x6d,0x6d,0x6f,0x2d,0x1d,0x63,0x7a, - 0x7e,0x75,0x5d,0x19,0x32,0x70,0x70,0x6f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7e,0x7d,0x53,0x35,0x0b,0x1f,0x0e,0x34,0x5a,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x7f,0x7e,0x7e,0x7e, - 0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e, - 0x7e,0x7e,0x7e,0x7e,0x0a,0x0a,0x0a,0x00,0x0b,0x0b,0x0b,0x00,0x16,0x16,0x16,0x00, - 0x1f,0x1f,0x1f,0x00,0x28,0x28,0x28,0x00,0x2d,0x2d,0x2d,0x00,0x35,0x35,0x35,0x00, - 0x3d,0x3d,0x3d,0x00,0x40,0x40,0x40,0x00,0x41,0x41,0x41,0x00,0x43,0x43,0x43,0x00, - 0x46,0x46,0x46,0x00,0x47,0x47,0x47,0x00,0x4b,0x4b,0x4b,0x00,0x4e,0x4e,0x4e,0x00, - 0x53,0x53,0x53,0x00,0x54,0x54,0x54,0x00,0x56,0x56,0x56,0x00,0x59,0x59,0x59,0x00, - 0x5a,0x5a,0x5a,0x00,0x5f,0x5f,0x5f,0x00,0x60,0x60,0x60,0x00,0x62,0x62,0x62,0x00, - 0x63,0x63,0x63,0x00,0x6a,0x6a,0x6a,0x00,0x74,0x74,0x74,0x00,0x75,0x75,0x75,0x00, - 0x76,0x76,0x76,0x00,0x78,0x78,0x78,0x00,0x79,0x79,0x79,0x00,0x7a,0x7a,0x7a,0x00, - 0x7c,0x7c,0x7c,0x00,0x7d,0x7d,0x7d,0x00,0x7e,0x7e,0x7e,0x00,0x80,0x80,0x80,0x00, - 0x81,0x81,0x81,0x00,0x82,0x82,0x82,0x00,0x83,0x83,0x83,0x00,0x84,0x84,0x84,0x00, - 0x85,0x85,0x85,0x00,0x87,0x87,0x87,0x00,0x88,0x88,0x88,0x00,0x89,0x89,0x89,0x00, - 0x8a,0x8a,0x8a,0x00,0x8b,0x8b,0x8b,0x00,0x8e,0x8e,0x8e,0x00,0x90,0x90,0x90,0x00, - 0x91,0x91,0x91,0x00,0x92,0x92,0x92,0x00,0x94,0x94,0x94,0x00,0x95,0x95,0x95,0x00, - 0x96,0x96,0x96,0x00,0x97,0x97,0x97,0x00,0x98,0x98,0x98,0x00,0x9b,0x9b,0x9b,0x00, - 0x9c,0x9c,0x9c,0x00,0x9d,0x9d,0x9d,0x00,0xa0,0xa0,0xa0,0x00,0xa1,0xa1,0xa1,0x00, - 0xa2,0xa2,0xa2,0x00,0xa4,0xa4,0xa4,0x00,0xa6,0xa6,0xa6,0x00,0xa7,0xa7,0xa7,0x00, - 0xab,0xab,0xab,0x00,0xac,0xac,0xac,0x00,0xad,0xad,0xad,0x00,0xae,0xae,0xae,0x00, - 0xaf,0xaf,0xaf,0x00,0xb0,0xb0,0xb0,0x00,0xb1,0xb1,0xb1,0x00,0xb2,0xb2,0xb2,0x00, - 0xb3,0xb3,0xb3,0x00,0xb4,0xb4,0xb4,0x00,0xb5,0xb5,0xb5,0x00,0xb6,0xb6,0xb6,0x00, - 0xb7,0xb7,0xb7,0x00,0xb9,0xb9,0xb9,0x00,0xbb,0xbb,0xbb,0x00,0xbc,0xbc,0xbc,0x00, - 0xbe,0xbe,0xbe,0x00,0xbf,0xbf,0xbf,0x00,0xc0,0xc0,0xc0,0x00,0xc1,0xc1,0xc1,0x00, - 0xc2,0xc2,0xc2,0x00,0xc3,0xc3,0xc3,0x00,0xc4,0xc4,0xc4,0x00,0xc5,0xc5,0xc5,0x00, - 0xc9,0xc9,0xc9,0x00,0xcb,0xcb,0xcb,0x00,0xcc,0xcc,0xcc,0x00,0xce,0xce,0xce,0x00, - 0xcf,0xcf,0xcf,0x00,0xd0,0xd0,0xd0,0x00,0xd1,0xd1,0xd1,0x00,0xd2,0xd2,0xd2,0x00, - 0xd4,0xd4,0xd4,0x00,0xd5,0xd5,0xd5,0x00,0xd6,0xd6,0xd6,0x00,0xd9,0xd9,0xd9,0x00, - 0xda,0xda,0xda,0x00,0xdb,0xdb,0xdb,0x00,0xdc,0xdc,0xdc,0x00,0xdd,0xdd,0xdd,0x00, - 0xe0,0xe0,0xe0,0x00,0xe1,0xe1,0xe1,0x00,0xe2,0xe2,0xe2,0x00,0xe3,0xe3,0xe3,0x00, - 0xe4,0xe4,0xe4,0x00,0xe6,0xe6,0xe6,0x00,0xe8,0xe8,0xe8,0x00,0xe9,0xe9,0xe9,0x00, - 0xea,0xea,0xea,0x00,0xeb,0xeb,0xeb,0x00,0xec,0xec,0xec,0x00,0xed,0xed,0xed,0x00, - 0xee,0xee,0xee,0x00,0xf0,0xf0,0xf0,0x00,0xf3,0xf3,0xf3,0x00,0xf4,0xf4,0xf4,0x00, - 0xf5,0xf5,0xf5,0x00,0xf7,0xf7,0xf7,0x00,0xf8,0xf8,0xf8,0x00,0xf9,0xf9,0xf9,0x00, - 0xfa,0xfa,0xfa,0x00,0xfb,0xfb,0xfb,0x00,0xfc,0xfc,0xfc,0x00,0xff,0xff,0xff,0x00, - 0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00 -}; +/* + + Support for Garmin Points of Interest (.gpi files) + + Copyright (C) 2007 Olaf Klein, o.b.klein@gpsbabel.org + Copyright (C) 2007-2012 Robert Lipe, robertlipe+source@gpsbabel.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ +#ifndef GARMIN_GPI_H_INCLUDED_ +#define GARMIN_GPI_H_INCLUDED_ + +/* + History: + + * 2007/05/18: initial release (only a reader) + * 2007/05/20: added writer code with embedded bitmap + * 2007/05/22: add support for multiple bounding boxes + (useful / required!) for large waypoints lists + * 2007/05/23: add optional user bitmap + * 2007/06/02: new method to compute center (mean) of bounds + avoid endless loop in group splitting + * 2007/07/10: put address fields (i.e. city) into GMSD + * 2007/07/12: add write support for new address fields + * 2007/10/20: add option unique + * 2007/12/02: support speed and proximity distance (+ alerts) + * 2008/01/14: fix structure error after adding speed/proximity + * 2008/03/22: add options "speed" and "proximity" (default values) and "sleep" + + ToDo: + + * Display mode ("Symbol & Name") ??? not in gpi ??? + * support category from GMSD "Garmin Special Data" +*/ + +#include // for QByteArray +#include // for QList +#include // for QString +#include // for QVector + +#include // for int32_t, int16_t, uint16_t +#include // for time_t + +#include "defs.h" // for arglist_t, ARG_NOMINMAX, ff_cap, Waypoint, ARGTYPE_BOOL, ARGTYPE_STRING, ff_cap_none, ARGTYPE_FILE, ARGTYPE_INT, CET_CHARSET_MS_ANSI, bounds, ff_cap_read, ff_cap_write, ff_type, ff_type_file, short_handle +#include "format.h" // for Format +#include "garmin_fs.h" // for garmin_fs_t +#include "garmin_gpi.h" // lines 66-66 +#include "gbfile.h" // for gbfile + + +class GarminGPIFormat : public Format +{ +public: + QVector* get_args() override + { + return &garmin_gpi_args; + } + + ff_type get_type() const override + { + return ff_type_file; + } + + QVector get_cap() const override + { + return { + (ff_cap)(ff_cap_read | ff_cap_write) /* waypoints */, + ff_cap_none /* tracks */, + ff_cap_none /* routes */ + }; + } + + QString get_encode() const override + { + return CET_CHARSET_MS_ANSI; /* WIN-CP1252 */ + } -#define GPI_BITMAP_SIZE sizeof(gpi_bitmap) + int get_fixed_encode() const override + { + return 0; + } + + void rd_init(const QString& fname) override; + void read() override; + void rd_deinit() override; + void wr_init(const QString& fname) override; + void write() override; + void wr_deinit() override; + +private: + /* Types */ + + struct reader_data_t { + int D2{}; + char S3[9]{}; /* "GRMRECnn" */ + time_t crdate{}; /* creation date and time */ + char POI[4]{}; /* "POI" */ + char S8[3]{}; + QString group; + QString category; + }; + + struct writer_data_t { + QList waypt_list; + int sz{0}; + int alert{0}; + bounds bds{}; + writer_data_t* top_left{nullptr}; + writer_data_t* top_right{nullptr}; + writer_data_t* bottom_left{nullptr}; + writer_data_t* bottom_right{nullptr}; + }; + + struct gpi_waypt_data_t { + int sz; + char* addr; + char* postal_code; + }; + + struct bmp_header_t { + int32_t size; + int16_t res1; + int16_t res2; + int32_t image_offset; + int32_t header_size; + int32_t width; + int32_t height; + int16_t planes; + int16_t bpp; + int32_t compression_type; + int32_t image_data_size; + int32_t resolution_h; + int32_t resolution_v; + int32_t used_colors; + int32_t important_colors; + }; + + struct gpi_bitmap_header_t { + int16_t index; + int16_t height; + int16_t width; + int16_t line_sz; + int16_t bpp; + int16_t fixed_0; + int32_t image_size; + int32_t fixed_2c; + int32_t palette_size; + int32_t tr_color; + int32_t flag2; + int32_t size_2c; + }; + + struct gpi_waypt_t { + int sz{0}; + int alerts{0}; + short mask{0}; + QString addr; + QString city; + QString country; + QString phone_nr; + QString postal_code; + QString state; + }; + + struct lc_string { + QByteArray lc; + QByteArray str; + int strlen{0}; + }; + + /* Constants */ + static constexpr unsigned char gpi_bitmap[] = { + 0x00,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x08,0x00,0x00,0x00,0x40,0x02,0x00,0x00, + 0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xff,0x00,0xff,0x00,0x01,0x00,0x00,0x00, + 0x6c,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x7e,0x7e,0x7e, + 0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e, + 0x7e,0x7e,0x00,0x7e,0x00,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, + 0x7f,0x7f,0x59,0x67,0x65,0x7f,0x7f,0x7f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f, + 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x74,0x3d,0x42,0x56,0x7e,0x7e,0x7f, + 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, + 0x7f,0x72,0x38,0x49,0x47,0x7e,0x7e,0x7f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f, + 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7d,0x37,0x47,0x7d,0x7e,0x7e,0x7f, + 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, + 0x7f,0x7d,0x37,0x47,0x7d,0x7e,0x7e,0x7f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f, + 0x7f,0x7f,0x7f,0x7f,0x7f,0x7c,0x6c,0x50,0x44,0x5e,0x4f,0x76,0x7e,0x7f,0x7f,0x7f, + 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x77,0x7e,0x7f,0x7f,0x7e,0x62,0x0d,0x00,0x05, + 0x10,0x08,0x09,0x59,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x29,0x1c, + 0x4c,0x7f,0x7f,0x60,0x02,0x0c,0x2a,0x37,0x51,0x63,0x57,0x15,0x58,0x7e,0x7e,0x7f, + 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x68,0x5a,0x41,0x5f,0x5f,0x07,0x0e,0x3d,0x41,0x41, + 0x4d,0x55,0x6b,0x61,0x26,0x57,0x57,0x2b,0x2f,0x30,0x00,0x7e,0x00,0x7e,0x77,0x7d, + 0x4e,0x3d,0x3d,0x16,0x35,0x41,0x7d,0x49,0x18,0x48,0x52,0x54,0x5b,0x31,0x31,0x63, + 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x40,0x7d,0x75,0x47,0x47,0x41,0x35,0x40,0x72,0x1e, + 0x7c,0x5d,0x1d,0x20,0x49,0x3d,0x3d,0x5b,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x60,0x5c, + 0x7a,0x1a,0x1a,0x3b,0x38,0x5d,0x0e,0x59,0x7d,0x3c,0x72,0x37,0x78,0x60,0x60,0x28, + 0x4f,0x71,0x00,0x7e,0x00,0x7e,0x7e,0x43,0x33,0x69,0x69,0x17,0x22,0x7d,0x2c,0x27, + 0x2a,0x2b,0x7d,0x32,0x61,0x4f,0x4f,0x36,0x3f,0x4c,0x00,0x7e,0x00,0x7e,0x7f,0x7e, + 0x3a,0x2b,0x2b,0x45,0x1a,0x40,0x47,0x7d,0x37,0x41,0x12,0x25,0x5e,0x46,0x46,0x4d, + 0x62,0x53,0x00,0x7e,0x00,0x7e,0x7f,0x7e,0x73,0x71,0x71,0x6a,0x13,0x39,0x1b,0x45, + 0x62,0x50,0x3a,0x7e,0x7e,0x7b,0x7b,0x5c,0x5b,0x49,0x00,0x7e,0x00,0x7e,0x7f,0x7e, + 0x59,0x01,0x01,0x06,0x64,0x35,0x4e,0x3e,0x26,0x21,0x66,0x7f,0x45,0x04,0x04,0x11, + 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7e,0x59,0x01,0x01,0x06,0x64,0x35,0x4e,0x3e, + 0x26,0x21,0x66,0x7f,0x45,0x04,0x04,0x11,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7e, + 0x7c,0x0a,0x0a,0x0f,0x65,0x7d,0x74,0x71,0x7c,0x7e,0x7e,0x7e,0x58,0x03,0x03,0x2b, + 0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f,0x7f,0x6d,0x6d,0x6f,0x2d,0x1d,0x63,0x7a, + 0x7e,0x75,0x5d,0x19,0x32,0x70,0x70,0x6f,0x7f,0x7f,0x00,0x7e,0x00,0x7e,0x7f,0x7f, + 0x7f,0x7f,0x7f,0x7e,0x7d,0x53,0x35,0x0b,0x1f,0x0e,0x34,0x5a,0x7f,0x7f,0x7f,0x7f, + 0x7f,0x7f,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x7f,0x7e,0x7e,0x7e, + 0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e, + 0x7e,0x7e,0x7e,0x7e,0x0a,0x0a,0x0a,0x00,0x0b,0x0b,0x0b,0x00,0x16,0x16,0x16,0x00, + 0x1f,0x1f,0x1f,0x00,0x28,0x28,0x28,0x00,0x2d,0x2d,0x2d,0x00,0x35,0x35,0x35,0x00, + 0x3d,0x3d,0x3d,0x00,0x40,0x40,0x40,0x00,0x41,0x41,0x41,0x00,0x43,0x43,0x43,0x00, + 0x46,0x46,0x46,0x00,0x47,0x47,0x47,0x00,0x4b,0x4b,0x4b,0x00,0x4e,0x4e,0x4e,0x00, + 0x53,0x53,0x53,0x00,0x54,0x54,0x54,0x00,0x56,0x56,0x56,0x00,0x59,0x59,0x59,0x00, + 0x5a,0x5a,0x5a,0x00,0x5f,0x5f,0x5f,0x00,0x60,0x60,0x60,0x00,0x62,0x62,0x62,0x00, + 0x63,0x63,0x63,0x00,0x6a,0x6a,0x6a,0x00,0x74,0x74,0x74,0x00,0x75,0x75,0x75,0x00, + 0x76,0x76,0x76,0x00,0x78,0x78,0x78,0x00,0x79,0x79,0x79,0x00,0x7a,0x7a,0x7a,0x00, + 0x7c,0x7c,0x7c,0x00,0x7d,0x7d,0x7d,0x00,0x7e,0x7e,0x7e,0x00,0x80,0x80,0x80,0x00, + 0x81,0x81,0x81,0x00,0x82,0x82,0x82,0x00,0x83,0x83,0x83,0x00,0x84,0x84,0x84,0x00, + 0x85,0x85,0x85,0x00,0x87,0x87,0x87,0x00,0x88,0x88,0x88,0x00,0x89,0x89,0x89,0x00, + 0x8a,0x8a,0x8a,0x00,0x8b,0x8b,0x8b,0x00,0x8e,0x8e,0x8e,0x00,0x90,0x90,0x90,0x00, + 0x91,0x91,0x91,0x00,0x92,0x92,0x92,0x00,0x94,0x94,0x94,0x00,0x95,0x95,0x95,0x00, + 0x96,0x96,0x96,0x00,0x97,0x97,0x97,0x00,0x98,0x98,0x98,0x00,0x9b,0x9b,0x9b,0x00, + 0x9c,0x9c,0x9c,0x00,0x9d,0x9d,0x9d,0x00,0xa0,0xa0,0xa0,0x00,0xa1,0xa1,0xa1,0x00, + 0xa2,0xa2,0xa2,0x00,0xa4,0xa4,0xa4,0x00,0xa6,0xa6,0xa6,0x00,0xa7,0xa7,0xa7,0x00, + 0xab,0xab,0xab,0x00,0xac,0xac,0xac,0x00,0xad,0xad,0xad,0x00,0xae,0xae,0xae,0x00, + 0xaf,0xaf,0xaf,0x00,0xb0,0xb0,0xb0,0x00,0xb1,0xb1,0xb1,0x00,0xb2,0xb2,0xb2,0x00, + 0xb3,0xb3,0xb3,0x00,0xb4,0xb4,0xb4,0x00,0xb5,0xb5,0xb5,0x00,0xb6,0xb6,0xb6,0x00, + 0xb7,0xb7,0xb7,0x00,0xb9,0xb9,0xb9,0x00,0xbb,0xbb,0xbb,0x00,0xbc,0xbc,0xbc,0x00, + 0xbe,0xbe,0xbe,0x00,0xbf,0xbf,0xbf,0x00,0xc0,0xc0,0xc0,0x00,0xc1,0xc1,0xc1,0x00, + 0xc2,0xc2,0xc2,0x00,0xc3,0xc3,0xc3,0x00,0xc4,0xc4,0xc4,0x00,0xc5,0xc5,0xc5,0x00, + 0xc9,0xc9,0xc9,0x00,0xcb,0xcb,0xcb,0x00,0xcc,0xcc,0xcc,0x00,0xce,0xce,0xce,0x00, + 0xcf,0xcf,0xcf,0x00,0xd0,0xd0,0xd0,0x00,0xd1,0xd1,0xd1,0x00,0xd2,0xd2,0xd2,0x00, + 0xd4,0xd4,0xd4,0x00,0xd5,0xd5,0xd5,0x00,0xd6,0xd6,0xd6,0x00,0xd9,0xd9,0xd9,0x00, + 0xda,0xda,0xda,0x00,0xdb,0xdb,0xdb,0x00,0xdc,0xdc,0xdc,0x00,0xdd,0xdd,0xdd,0x00, + 0xe0,0xe0,0xe0,0x00,0xe1,0xe1,0xe1,0x00,0xe2,0xe2,0xe2,0x00,0xe3,0xe3,0xe3,0x00, + 0xe4,0xe4,0xe4,0x00,0xe6,0xe6,0xe6,0x00,0xe8,0xe8,0xe8,0x00,0xe9,0xe9,0xe9,0x00, + 0xea,0xea,0xea,0x00,0xeb,0xeb,0xeb,0x00,0xec,0xec,0xec,0x00,0xed,0xed,0xed,0x00, + 0xee,0xee,0xee,0x00,0xf0,0xf0,0xf0,0x00,0xf3,0xf3,0xf3,0x00,0xf4,0xf4,0xf4,0x00, + 0xf5,0xf5,0xf5,0x00,0xf7,0xf7,0xf7,0x00,0xf8,0xf8,0xf8,0x00,0xf9,0xf9,0xf9,0x00, + 0xfa,0xfa,0xfa,0x00,0xfb,0xfb,0xfb,0x00,0xfc,0xfc,0xfc,0x00,0xff,0xff,0xff,0x00, + 0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00 + }; + + /* Member Functions */ + + static garmin_fs_t* gpi_gmsd_init(Waypoint* wpt); + lc_string gpi_read_lc_string() const; + QString gpi_read_string(const char* field) const; + void read_header(); + void read_poi(int sz, int tag); + void read_poi_list(int sz); + void read_poi_group(int sz, int tag); + int read_tag(const char* caller, int tag, Waypoint* wpt); + void write_string(const char* str, char long_format) const; + static bool compare_wpt_cb(const Waypoint* a, const Waypoint* b); + static char compare_strings(const QString& s1, const QString& s2); + static writer_data_t* wdata_alloc(); + static void wdata_free(GarminGPIFormat::writer_data_t* data); + static void wdata_add_wpt(GarminGPIFormat::writer_data_t* data, Waypoint* wpt); + void wdata_check(GarminGPIFormat::writer_data_t* data) const; + int wdata_compute_size(GarminGPIFormat::writer_data_t* data) const; + void wdata_write(const GarminGPIFormat::writer_data_t* data) const; + void write_category(const char* unused, const unsigned char* image, int image_sz) const; + void write_header() const; + void enum_waypt_cb(const Waypoint* ref) const; + static void load_bitmap_from_file(const char* fname, const unsigned char** data, int* data_sz); + + /* Data Members */ + + char* opt_cat{}, *opt_pos{}, *opt_notes{}, *opt_hide_bitmap{}, *opt_descr{}, *opt_bitmap{}; + char* opt_unique{}, *opt_alerts{}, *opt_units{}, *opt_speed{}, *opt_proximity{}, *opt_sleep{}; + char* opt_lang{}; + char* opt_writecodec{}; + double defspeed{}, defproximity{}; + int alerts{}; + + QVector garmin_gpi_args = { + { + "alerts", &opt_alerts, "Enable alerts on speed or proximity distance", + nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr + }, + { + "bitmap", &opt_bitmap, "Use specified bitmap on output", + nullptr, ARGTYPE_FILE, ARG_NOMINMAX, nullptr + }, + { + "category", &opt_cat, "Default category on output", + "My points", ARGTYPE_STRING, ARG_NOMINMAX, nullptr + }, + { + "hide", &opt_hide_bitmap, "Don't show gpi bitmap on device", + nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr + }, + { + "descr", &opt_descr, "Write description to address field", + nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr + }, + { + "notes", &opt_notes, "Write notes to address field", + nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr + }, + { + "position", &opt_pos, "Write position to address field", + nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr + }, + { + "proximity", &opt_proximity, "Default proximity", + nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr + }, + { + "sleep", &opt_sleep, "After output job done sleep n second(s)", + nullptr, ARGTYPE_INT, "1", nullptr, nullptr + }, + { + "speed", &opt_speed, "Default speed", + nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr + }, + { + "unique", &opt_unique, "Create unique waypoint names (default = yes)", + "Y", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr + }, + { + "units", &opt_units, "Units used for names with @speed ('s'tatute or 'm'etric)", + "m", ARGTYPE_STRING, ARG_NOMINMAX, nullptr + }, + { + "writecodec", &opt_writecodec, "codec to use for writing strings", + "windows-1252", ARGTYPE_STRING, ARG_NOMINMAX, nullptr + }, + { + "languagecode", &opt_lang, "language code to use for reading dual language files", + nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr + } + }; + + + gbfile* fin{}, *fout{}; + uint16_t codepage{}; /* code-page, e.g. 1252, 65001 */ + reader_data_t* rdata{}; + writer_data_t* wdata{}; + short_handle short_h{}; + char units{}; + time_t gpi_timestamp = 0; +}; -#endif +#endif // GARMIN_GPI_H_INCLUDED_ diff --git a/vecs.h b/vecs.h index 4f7611c7e..b6f315f9c 100644 --- a/vecs.h +++ b/vecs.h @@ -34,6 +34,7 @@ #include "exif.h" #include "format.h" #include "garmin_fit.h" +#include "garmin_gpi.h" #include "geojson.h" #include "ggv_bin.h" #include "globalsat_sport.h" @@ -103,7 +104,6 @@ extern ff_vecs_t garmin_txt_vecs; extern ff_vecs_t dmtlog_vecs; extern ff_vecs_t raymarine_vecs; extern ff_vecs_t ggv_log_vecs; -extern ff_vecs_t garmin_gpi_vecs; extern ff_vecs_t lmx_vecs; extern ff_vecs_t xol_vecs; extern ff_vecs_t navilink_vecs; @@ -281,7 +281,7 @@ private: LegacyFormat dmtlog_fmt {dmtlog_vecs}; LegacyFormat raymarine_fmt {raymarine_vecs}; LegacyFormat ggv_log_fmt {ggv_log_vecs}; - LegacyFormat garmin_gpi_fmt {garmin_gpi_vecs}; + GarminGPIFormat garmin_gpi_fmt; LegacyFormat lmx_fmt {lmx_vecs}; RandomFormat random_fmt; LegacyFormat xol_fmt {xol_vecs}; -- 2.30.2